package com.ctshk.rpc.hotel.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.hotel.HotelHasBreakfast;
import com.ctshk.common.enums.hotel.HotelStarLevel;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.hotel.dto.*;
import com.ctshk.rpc.hotel.dto.booking.HotelBookingDetailsDTO;
import com.ctshk.rpc.hotel.dto.booking.HotelBookingProductDTO;
import com.ctshk.rpc.hotel.dto.booking.HotelBookingRoomDTO;
import com.ctshk.rpc.hotel.dto.h5.HotelProductDTO;
import com.ctshk.rpc.hotel.dto.h5.HotelRoomDTO;
import com.ctshk.rpc.hotel.entity.*;
import com.ctshk.rpc.hotel.mapper.*;
import com.ctshk.rpc.hotel.req.*;
import com.ctshk.rpc.hotel.req.booking.HotelDetailsQueryReq;
import com.ctshk.rpc.hotel.req.h5.HotelDetailsQueryH5Req;
import com.ctshk.rpc.hotel.req.h5.RoomDetailsQueryH5Req;
import com.ctshk.rpc.hotel.service.IHotelService;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 酒店资源 服务实现类
 * </p>
 *
 * @author yinhuan
 * @since 2021-03-03
 */
@Slf4j
@DubboService
public class HotelServiceImpl extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
    /**  0-未删除  1-已删除*/
    public final static Integer NOT_DELETE = 0;
    public final static Integer IS_DELETED = 1;
    @Autowired
    private HotelMapper hotelMapper;
    @Autowired
    private HotelRoomTypeMapper hotelRoomTypeMapper;
    @Autowired
    private HotelFacilitiesMapper hotelFacilitiesMapper;
    @Autowired
    private HotelAdditionalMapper hotelAdditionalMapper;
    @Autowired
    private HotelProductMapper hotelProductMapper;
    @Autowired
    private HotelProductCostMapper hotelProductCostMapper;
    @Autowired
    private HotelProductCostDateMapper hotelProductCostDateMapper;
    @DubboReference
    private ISysDepartmentService sysDepartmentService;
    @Override
    public PageResponse<HotelListManagerDTO> queyList(HotelListManagerReq req) {
        IPage<HotelListManagerDTO> agentPage = new Page<>(req.getPageNo(),req.getPageSize());
        agentPage = hotelMapper.queryHotelList(req,agentPage);
        PageResponse<HotelListManagerDTO> result = new PageResponse<>(agentPage.getRecords(),agentPage.getCurrent() == 1,
                agentPage.getTotal() <= (agentPage.getCurrent() * agentPage.getSize()),
                agentPage.getTotal(), agentPage.getCurrent(), agentPage.getSize());
        return result;
    }

    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result saveHotel(HotelReq req, TokenUser user) {
        {
            if(user == null){
                return Result.failed(SystemError.USER_1000);
            }
            if(req == null){
                return Result.failed(SystemError.HOTEL_NULL_10012);
            }
            //保存酒店
            Hotel hotel = EntityUtil.copy(req, Hotel.class);
            LocalDateTime now = LocalDateTime.now();
            hotel.setSourceType(ProductType.MANUAL_ENTRY.getCode());
            hotel.setGmtCreate(now);
            hotel.setGmtModified(now);
            hotel.setCreateId(user.getId());
            hotel.setIsDeleted(IsDeletedCode.NO.getCode());
            long id = SnowflakeIdWorker.nextId();
            hotel.setId(id);
            // 默认设置第一张图片为酒店封面图
            if (StringUtils.isBlank(hotel.getCoverMap()) && !StringUtils.isBlank(hotel.getShowPhotoJson())) {
                JSONArray jsonArray = JSON.parseArray(hotel.getShowPhotoJson());
                JSONObject jsonObject = JSON.parseObject(jsonArray.get(0).toString());
                hotel.setCoverMap(jsonObject.getString("url"));
            }
            hotelMapper.insert(hotel);

            //保存酒店设施
            List<HotelFacilitiesReq> hotelFacilitiesReqList = req.getHotelFacilitiesReq();
            if(CollUtil.isNotEmpty(hotelFacilitiesReqList)){
                for (int i = 0; i <hotelFacilitiesReqList.size() ; i++) {
                    HotelFacilities hotelFacilities = EntityUtil.copy(req.getHotelFacilitiesReq().get(i), HotelFacilities.class);
                    long hotelFacilitiesId = SnowflakeIdWorker.nextId();
                    hotelFacilities.setId(hotelFacilitiesId);
                    hotelFacilities.setHotelId(hotel.getId());
                    hotelFacilities.setCreateId(user.getId());
                    hotelFacilities.setGmtCreate(now);
                    hotelFacilities.setIsDeleted(IsDeletedCode.NO.getCode());
                    hotelFacilitiesMapper.insert(hotelFacilities);
                }
            }
            return Result.success();
        }
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Result updateHotel(HotelReq req, TokenUser user) {

        if(user == null){
            return Result.failed(SystemError.USER_1000);
        }
        if(req == null){
            return Result.failed(SystemError.HOTEL_10011);
        }
        //现根据HorelId查出酒店信息
        Hotel hotel = hotelMapper.selectById(req.getId());
        if(Objects.isNull(hotel)){
            return Result.failed(SystemError.HOTEL_10010);
        }
        //修改酒店信息
        hotel.setModifiedId(user.getId());
        hotel.setGmtModified(LocalDateTime.now());
        BeanUtils.copyProperties(req,hotel);
        hotel.setHotelPolicy(req.getHotelPolicy());
        hotel.setShowPhotoJson(req.getShowPhotoJson());
        hotel.setPostalCode(req.getPostalCode());
        hotel.setSourceType(ProductType.MANUAL_ENTRY.getCode());
        hotel.setCreateId(user.getId());
        hotel.setIsDeleted(NOT_DELETE);
        hotel.setFaxNumber(req.getFaxNumber());
        Hotel hotelObj = EntityUtil.copy(hotel, Hotel.class);
        // 默认设置第一张图片为酒店封面图
        if (StringUtils.isBlank(hotel.getCoverMap()) && !StringUtils.isBlank(req.getShowPhotoJson()) && StringUtils.isBlank(req.getCoverMap())) {
            JSONArray jsonArray = JSON.parseArray(req.getShowPhotoJson());
            JSONObject jsonObject = JSON.parseObject(jsonArray.get(0).toString());
            hotelObj.setCoverMap(jsonObject.getString("url"));
        }
        hotelMapper.updateById(hotelObj);
        List<Long> hotelFacilitiesIdList = new ArrayList<Long>();
        //删除该酒店下所有设施信息
        if(req.getHotelFacilitiesReq()!=null){
            QueryWrapper<HotelFacilities> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(HotelFacilities::getHotelId,hotel.getId());
            queryWrapper.lambda().eq(HotelFacilities::getIsDeleted, IsDeletedCode.NO.getCode());
            List<HotelFacilities> hotelFacilities = hotelFacilitiesMapper.selectList(queryWrapper);
            for(int i=0;i<hotelFacilities.size();i++){
                hotelFacilitiesMapper.deleteById(hotelFacilities.get(i).getId());
            }
            //添加酒店设施信息
            for (int i = 0; i <req.getHotelFacilitiesReq().size() ; i++) {
                HotelFacilities hotelFacilitiesObj = EntityUtil.copy(req.getHotelFacilitiesReq().get(i), HotelFacilities.class);
                long hotelFacilitiesId = IdWorker.getId();
                hotelFacilitiesIdList.add(hotelFacilitiesId);
                hotelFacilitiesObj.setId(hotelFacilitiesId);
                hotelFacilitiesObj.setHotelId(hotel.getId());
                hotelFacilitiesObj.setCreateId(user.getId());
                hotelFacilitiesObj.setGmtCreate(LocalDateTime.now());
                hotelFacilitiesObj.setIsDeleted(IsDeletedCode.NO.getCode());
                hotelFacilitiesMapper.insert(hotelFacilitiesObj);
            }
        }
        return Result.success(hotelFacilitiesIdList);
    }

    /**
     * 查询酒店情信息
     * @param id
     * @return
     */
    @Override
    public HotelListDTO queryDetail(Long id) {
        Hotel hotel = hotelMapper.selectById(id);
        HotelListDTO hotelListDTO = new HotelListDTO();
        BeanUtils.copyProperties(hotel,hotelListDTO);
        //加入酒店设施信息
        List<Long> hotelFacilitiesIdList = new ArrayList<Long>();
        List<HotelFacilities> hotelFacilitiesList =  hotelFacilitiesMapper.selectList(new QueryWrapper<HotelFacilities>().lambda().eq(HotelFacilities::getHotelId, hotel.getId()));
        if(hotelFacilitiesList.size()>0){
            List<HotelFacilitiesDTO> hotelFacilitiesDTO = EntityUtil.copyList(hotelFacilitiesList, HotelFacilitiesDTO.class);
            hotelListDTO.setHotelFacilitiesDTO(hotelFacilitiesDTO);
        }
        return hotelListDTO;
    }


    /**
     * 根据id数组查询酒店详情
     * @param idList
     * @return
     */
    @Override
    public List<HotelListDTO> queryDetailList(List<Long> idList) {
        List<Hotel> hotelList = hotelMapper.selectList(Wrappers.<Hotel>lambdaQuery()
        .in(Hotel::getId,idList));
        return EntityUtil.copyList(hotelList, HotelListDTO.class);
    }


    /**
     * 酒店房型資源列表查询
     *
     * @param req 入参
     * @return
     */
    @Override
    public PageResponse<HotelQueryDTO> queryAllHotelList(HotelQueryReq req) {
        IPage<HotelQueryDTO> hotelPage = new Page<>(req.getPageNo(),req.getPageSize());
        hotelPage = hotelMapper.queryAllHotelList(req,hotelPage);
        PageResponse<HotelQueryDTO> result = new PageResponse<>(hotelPage.getRecords(),hotelPage.getCurrent() == 1,
                hotelPage.getTotal() <= (hotelPage.getCurrent() * hotelPage.getSize()),
                hotelPage.getTotal(), hotelPage.getCurrent(), hotelPage.getSize());
        return result;
    }

    @Override
    public PageResponse<HotelQueryListDTO> queryList(HotelOrderQueryReq req, Long userId) {
        List<LocalDate> dates = DateUtil.getMiddleDate(req.getCheckInDate(), req.getCheckOutDate());
        // 如果时间大于1天,则删除最后一天的日期,因为最后一天是离店时间不算入住
        if (dates.size() > 1) {
            dates.remove(dates.size() - 1);
        }
        // 获取当前用户所有上级部门id,并把自己用户id加入list中,目的是查询整个关联字段
        List<Long> deptIds = new ArrayList<>();
        deptIds.add(userId);
        deptIds.addAll(sysDepartmentService.queryIdsByUserId(userId));
        boolean isAddBed = true;
        // 总人数%房间数,如果不可以除尽则只查询可以加床的酒店产品,反之则不限制
        if (req.getPeopleNum() % req.getRoomNum() != 0) {
            req.setIsAddBed(isAddBed);
        }
        req.setPeopleNum(req.getPeopleNum() / req.getRoomNum());
        // 查詢酒店
        Page<HotelQueryListDTO> page = new Page<>(req.getPageNo(),req.getPageSize());
        Page<HotelQueryListDTO> resultPage = hotelProductMapper.queryHotels(page, dates, deptIds, req);
        Optional.ofNullable(resultPage.getRecords()).orElse(new ArrayList<>()).forEach(record -> {
            int days = DateUtil.daysBetween(req.getCheckInDate(), req.getCheckOutDate());
            // 如果天数是0则默认改成1,防止天数为0时价格被变成0
            days = days == 0 ? 1 : days;
            // 列表中酒店价格 = 单价 * 天数(B端查询列表显示天数总价)
            record.setPrice(record.getPrice() == null ? BigDecimal.ZERO : record.getPrice().multiply(new BigDecimal(days)));
            record.setStarLevelExplain(HotelStarLevel.parseValue(record.getStarLevel()));
        });
        return new PageResponse<>(resultPage.getRecords(), resultPage.getCurrent() == 1, resultPage.getTotal() <= (resultPage.getCurrent() * resultPage.getSize()), resultPage.getTotal(), resultPage.getCurrent(), resultPage.getSize());
    }

    @Override
    public PageResponse<HotelQueryListDTO> queryListH5(com.ctshk.rpc.hotel.req.h5.HotelQueryReq req) {
        List<LocalDate> dates = DateUtil.getMiddleDate(req.getCheckInDate(), req.getCheckOutDate());
        // 如果时间大于1天,则删除最后一天的日期,因为最后一天是离店时间不算入住
        if (dates.size() > 1) {
            dates.remove(dates.size() - 1);
        }
        // 总人数%房间数,如果不可以除尽则只查询可以加床的酒店产品,反之则不限制
        int totalNum = req.getAdultNum() + req.getChildrenNum();
        if (totalNum % req.getRoomNum() != 0) {
            req.setIsAddBed(true);
        }
        req.setPeopleNum(totalNum / req.getRoomNum());
        // 查詢酒店
        Page<HotelQueryListDTO> page = new Page<>(req.getPageNo(),req.getPageSize());
        // 搜索时城市去掉'市'字方便查询
        if (StringUtils.isNotBlank(req.getCityName())) {
            req.setCityName(req.getCityName().replace("市", ""));
        }
        Page<HotelQueryListDTO> resultPage = hotelProductMapper.queryHotelsH5(page, req, dates, ChannelMainData.APP_H5.getId(), ChannelMainData.CHINA_TRAVEL.getId());
        Optional.ofNullable(resultPage.getRecords()).orElse(new ArrayList<>()).forEach(record -> {
            record.setPrice(record.getPrice() == null ? BigDecimal.ZERO : record.getPrice().setScale(0, BigDecimal.ROUND_UP));
            record.setStarLevelExplain(HotelStarLevel.parseValue(record.getStarLevel()));

            String isSecCheck = record.getIsSecCheck() != null && record.getIsSecCheck() == 1 ? "即時確認" : "限時確認";
            String allowRefund = record.getAllowRefund() != null && record.getAllowRefund() == 1 ? "限時取消" : "不退不改";
            record.setConfirm(StrUtil.concat(true, isSecCheck, " ", allowRefund));
        });
        return new PageResponse<>(resultPage.getRecords(), resultPage.getCurrent() == 1, resultPage.getTotal() <= (resultPage.getCurrent() * resultPage.getSize()), resultPage.getTotal(), resultPage.getCurrent(), resultPage.getSize());
    }

    @Override
    public List<HotelQueryListDTO> queryRecommendationList(Long userId) {
        // 获取当前用户所有上级部门id,并把自己用户id加入list中,目的是查询整个关联字段
        List<Long> deptIds = new ArrayList<>();
        deptIds.add(userId);
        deptIds.addAll(sysDepartmentService.queryIdsByUserId(userId));

        String now = DateUtil.fmt(LocalDateTime.now());

        List<Long> hotelIds = hotelProductMapper.queryRecommendedIds(deptIds, now);

        if(CollectionUtils.isEmpty(hotelIds)){
            return new ArrayList<>();
        }

        List<HotelQueryListDTO> hotels = new ArrayList<>();
        // 遍历酒店获取相关信息,如酒店产品当天最低价
        hotelIds.forEach(hotelId -> {
            log.info("获取hotelId为[{}]的酒店产品当天最低价", hotelId);
            HotelQueryListDTO hotelQueryListDTOS = hotelProductMapper.queryProductsMin(deptIds, now, hotelId);
            if (null != hotelQueryListDTOS) {
                hotelQueryListDTOS.setStarLevelExplain(HotelStarLevel.parseValue(hotelQueryListDTOS.getStarLevel()));
                hotelQueryListDTOS.setPrice(hotelQueryListDTOS.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
                hotels.add(hotelQueryListDTOS);
            }
        });

        return hotels;
    }

    @Override
    public List<HotelQueryListDTO> queryRecommendationListH5(String now) {

        List<Long> hotelIds = hotelProductMapper.queryRecommendedIdsH5(now, null, ChannelMainData.APP_H5.getId(), ChannelMainData.CHINA_TRAVEL.getId());

        if(CollectionUtils.isEmpty(hotelIds)) {
            return new ArrayList<>();
        }

        List<HotelQueryListDTO> hotels = new ArrayList<>();
        // 遍历酒店获取相关信息,如酒店产品当天最低价
        for (Long hotelId : hotelIds) {
            HotelQueryListDTO hotelQueryListDTOS = hotelProductMapper.queryProductsMinH5(now, hotelId);
            if (null != hotelQueryListDTOS) {
                hotelQueryListDTOS.setStarLevelExplain(HotelStarLevel.parseValue(hotelQueryListDTOS.getStarLevel()));
                // C端价格向上取整数,不留小数
                hotelQueryListDTOS.setPrice(hotelQueryListDTOS.getPrice() == null ? BigDecimal.ZERO : hotelQueryListDTOS.getPrice().setScale(0, BigDecimal.ROUND_UP));
                hotels.add(hotelQueryListDTOS);
            }
        }

        return hotels;
    }

    @Override
    public List<HotelQueryListDTO> queryRecommendationListPC(String now, String city) {

        List<Long> hotelIds = hotelProductMapper.queryRecommendedIdsH5(now, city, ChannelMainData.APP_H5.getId(), ChannelMainData.CHINA_TRAVEL.getId());

        if(CollectionUtils.isEmpty(hotelIds)) {
            return new ArrayList<>();
        }

        List<HotelQueryListDTO> hotels = new ArrayList<>();
        // 遍历酒店获取相关信息,如酒店产品当天最低价
        for (Long hotelId : hotelIds) {
            HotelQueryListDTO hotelQueryListDTOS = hotelProductMapper.queryProductsMinH5(now, hotelId);
            if (null != hotelQueryListDTOS) {
                hotelQueryListDTOS.setStarLevelExplain(HotelStarLevel.parseValue(hotelQueryListDTOS.getStarLevel()));
                // C端价格向上取整数,不留小数
                hotelQueryListDTOS.setPrice(hotelQueryListDTOS.getPrice() == null ? BigDecimal.ZERO : hotelQueryListDTOS.getPrice().setScale(0, BigDecimal.ROUND_UP));
                hotels.add(hotelQueryListDTOS);
            }
        }

        return hotels;
    }

    @Override
    public HotelBookingDetailsDTO details(HotelDetailsQueryReq req, Long userId) {
        Hotel hotel = hotelMapper.selectById(req.getId());
        if (null == hotel || hotel.getIsDeleted() == 1) {
            throw new BusinessException(SystemError.HOTEL_10010);
        }

        List<LocalDate> dates = DateUtil.getMiddleDate(req.getCheckInDate(), req.getCheckOutDate());
        int dateType = 2;
        // 如果时间大于1天,则删除最后一天的日期,因为最后一天是离店时间不算入住
        if (dates.size() > 1) {
            dates.remove(dates.size() - 1);
            dateType = 1;
        }
        if (dates.size() == 1) {
            dateType = 2;
        }

        HotelBookingDetailsDTO hotelBookingDetailsDTO = EntityUtil.copy(hotel, HotelBookingDetailsDTO.class);
        hotelBookingDetailsDTO.setLng(hotel.getLongitude());
        hotelBookingDetailsDTO.setLat(hotel.getLatitude());
        List<HotelRoomType> hotelRoomTypes = hotelRoomTypeMapper.selectList(Wrappers.<HotelRoomType>lambdaQuery()
                .eq(HotelRoomType::getHotelId, hotel.getId())
                .ge(HotelRoomType::getMaxAdult,req.getPeopleNum() / req.getRoomNum())
                // 总人数%房间数,如果不可以除尽则只查询可以加床的酒店产品,反之则不限制
                .eq(req.getPeopleNum() % req.getRoomNum() != 0, HotelRoomType::getCanAddBed,1)
                .eq(HotelRoomType::getIsDeleted,0)
        );
        hotelBookingDetailsDTO.setStarLevel(Integer.parseInt(hotel.getStarLevel()));
        hotelBookingDetailsDTO.setStarLevelExplain(HotelStarLevel.parseValue(Integer.parseInt(hotel.getStarLevel())));
        List<HotelBookingRoomDTO> hotelBookingRoomDTOS = new ArrayList<>();
        // 获取当前用户所有上级部门id,并把自己用户id加入list中,目的是查询整个关联字段
        List<Long> deptIds = new ArrayList<>();
        deptIds.add(userId);
        deptIds.addAll(sysDepartmentService.queryIdsByUserId(userId));
        req.setPeopleNum(req.getPeopleNum() / req.getRoomNum());
        // 遍历房型数组获取满足条件的产品
        for (HotelRoomType hotelRoomType : hotelRoomTypes) {
            HotelBookingRoomDTO hotelBookingRoom = EntityUtil.copy(hotelRoomType, HotelBookingRoomDTO.class);
            // 获取指定房型的产品
            req.setRoomId(hotelRoomType.getId());
            List<HotelBookingProductDTO> hotelBookingProductDTOS = hotelProductMapper.queryProducts(deptIds, req, userId, dates, dateType);
            if (CollUtil.isEmpty(hotelBookingProductDTOS)) {
                // 当前房型没有匹配产品,退出当前遍历
                continue;
            }
            for (HotelBookingProductDTO hotelBookingProduct : hotelBookingProductDTOS) {
                hotelBookingProduct.setRemainStock(null == hotelBookingProduct.getRemainStock() ? 0 : hotelBookingProduct.getRemainStock());
                hotelBookingProduct.setRemainSaleableNumber(null == hotelBookingProduct.getRemainSaleableNumber() ? 0 : hotelBookingProduct.getRemainSaleableNumber());
                // 产品的库存余票数量大于用户剩余可售数量,剩余可售数量就是实际酒店产品余票,反之就是库存余票数为实际酒店产品余票
                if (hotelBookingProduct.getRemainStock() > hotelBookingProduct.getRemainSaleableNumber()) {
                    hotelBookingProduct.setStock(hotelBookingProduct.getRemainSaleableNumber());
                } else {
                    hotelBookingProduct.setStock(hotelBookingProduct.getRemainStock());
                }
                if (StringUtils.isNotBlank(hotelBookingProduct.getHasBreakfast())) {
                    hotelBookingProduct.setHasBreakfast(HotelHasBreakfast.parseValue(Integer.parseInt(hotelBookingProduct.getHasBreakfast())));
                }
                hotelBookingProduct.setMaxAdult(hotelBookingRoom.getMaxAdult());
                hotelBookingProduct.setIsSecCheck(StringUtils.equals(hotelBookingProduct.getIsSecCheck(), "1") ? "預訂後還需要確認" : "即時確認");
            }
            hotelBookingRoom.setHotelProducts(hotelBookingProductDTOS);

            hotelBookingRoom.setAreaMeasure(hotelRoomType.getAreaMeasure() + "㎡");
            hotelBookingRoom.setMaxAdult(hotelRoomType.getMaxAdult() + "人");
            hotelBookingRoom.setRoomFloors(hotelRoomType.getRoomFloors() + "層");
            hotelBookingRoom.setAllowSmoke(hotelRoomType.getAllowSmoke() == 1 ? "允許" : "不允許");
            hotelBookingRoom.setCanAddBed(hotelRoomType.getCanAddBed() == 1 ? "可加 " + hotelRoomType.getAddBedNumber() + "張" : "不可加");
            hotelBookingRoom.setHasWindow(hotelRoomType.getHasWindow() == 1 ? "有窗" : "無窗");
            if (null == hotelRoomType.getIsFreeNet()) {
                hotelBookingRoom.setIsFreeNet("/");
            } else {
                hotelBookingRoom.setIsFreeNet(hotelRoomType.getIsFreeNet() == 1 ? "免費" : "收費");
            }

            hotelBookingRoomDTOS.add(hotelBookingRoom);
        }

        hotelBookingDetailsDTO.setHotelRooms(hotelBookingRoomDTOS);
        return hotelBookingDetailsDTO;
    }

    @Override
    public Result<HotelBookingDetailsDTO> detailsH5(HotelDetailsQueryH5Req req) {
        Hotel hotel = hotelMapper.selectById(req.getId());
        if (null == hotel || hotel.getIsDeleted() == 1) {
            return Result.failed(SystemError.HOTEL_10010);
        }
        List<LocalDate> dates = DateUtil.getMiddleDate(req.getCheckInDate(), req.getCheckOutDate());
        int dateType = 2;
        // 如果时间大于1天,则删除最后一天的日期,因为最后一天是离店时间不算入住
        if (dates.size() > 1) {
            dates.remove(dates.size() - 1);
            dateType = 1;
        }
        if (dates.size() == 1) {
            dateType = 2;
        }
        req.setAdultNum(req.getAdultNum() == null ? 0 : req.getAdultNum());
        req.setChildrenNum(req.getChildrenNum() == null ? 0 : req.getChildrenNum());
        int totalNum = req.getAdultNum() + req.getChildrenNum();

        // 防止房间数为空
        req.setRoomNum(req.getRoomNum() == null || req.getRoomNum() == 0 ? 1 : req.getRoomNum());

        req.setPeopleNum(totalNum / req.getRoomNum());
        HotelBookingDetailsDTO hotelBookingDetailsDTO = EntityUtil.copy(hotel, HotelBookingDetailsDTO.class);
        hotelBookingDetailsDTO.setLng(hotel.getLongitude());
        hotelBookingDetailsDTO.setLat(hotel.getLatitude());
        List<HotelRoomType> hotelRoomTypes = hotelRoomTypeMapper.selectList(Wrappers.<HotelRoomType>lambdaQuery()
                .eq(HotelRoomType::getHotelId, hotel.getId())
                .ge(HotelRoomType::getMaxAdult,req.getPeopleNum() / req.getRoomNum())
                // 总人数%房间数,如果不可以除尽则只查询可以加床的酒店产品,反之则不限制
                .eq(req.getPeopleNum() % req.getRoomNum() != 0, HotelRoomType::getCanAddBed,1)
                .eq(HotelRoomType::getIsDeleted,0)
        );
        hotelBookingDetailsDTO.setStarLevel(Integer.parseInt(hotel.getStarLevel()));
        hotelBookingDetailsDTO.setStarLevelExplain(HotelStarLevel.parseValue(Integer.parseInt(hotel.getStarLevel())));
        List<HotelBookingRoomDTO> hotelBookingRoomDTOS = new ArrayList<>();

        req.setPeopleNum(req.getPeopleNum() / req.getRoomNum());
        // 遍历房型数组获取满足条件的产品
        for (HotelRoomType hotelRoomType : hotelRoomTypes) {
            HotelBookingRoomDTO hotelBookingRoom = EntityUtil.copy(hotelRoomType, HotelBookingRoomDTO.class);
            // 获取指定房型的产品
            req.setRoomId(hotelRoomType.getId());
            List<HotelBookingProductDTO> hotelBookingProductDTOS = hotelProductMapper.queryProductsH5(req, dates, dateType, ChannelMainData.APP_H5.getId(), ChannelMainData.CHINA_TRAVEL.getId());
            if (CollUtil.isEmpty(hotelBookingProductDTOS)) {
                // 当前房型没有匹配产品,退出当前遍历
                continue;
            }
            for (HotelBookingProductDTO hotelBookingProduct : hotelBookingProductDTOS) {
                hotelBookingProduct.setRemainStock(null == hotelBookingProduct.getRemainStock() ? 0 : hotelBookingProduct.getRemainStock());
                hotelBookingProduct.setRemainSaleableNumber(null == hotelBookingProduct.getRemainSaleableNumber() ? 0 : hotelBookingProduct.getRemainSaleableNumber());
                // 产品的库存余票数量大于用户剩余可售数量,剩余可售数量就是实际酒店产品余票,反之就是库存余票数为实际酒店产品余票
                if (hotelBookingProduct.getRemainStock() > hotelBookingProduct.getRemainSaleableNumber()) {
                    hotelBookingProduct.setStock(hotelBookingProduct.getRemainSaleableNumber());
                } else {
                    hotelBookingProduct.setStock(hotelBookingProduct.getRemainStock());
                }
                hotelBookingProduct.setMaxAdult(hotelBookingRoom.getMaxAdult());
                hotelBookingProduct.setPrice(hotelBookingProduct.getPrice() == null ? BigDecimal.ZERO : hotelBookingProduct.getPrice().setScale(0, BigDecimal.ROUND_UP));
            }
            hotelBookingRoom.setHotelProducts(hotelBookingProductDTOS);

            hotelBookingRoom.setAreaMeasure(hotelRoomType.getAreaMeasure() + "㎡");
            hotelBookingRoom.setMaxAdult(hotelRoomType.getMaxAdult() + "人");
            hotelBookingRoom.setRoomFloors(hotelRoomType.getRoomFloors() + "層");
            hotelBookingRoom.setAllowSmoke(hotelRoomType.getAllowSmoke() == 1 ? "允許" : "不允許");
            hotelBookingRoom.setCanAddBed(hotelRoomType.getCanAddBed() == 1 ? "可加 " + hotelRoomType.getAddBedNumber() + "張" : "不可加");
            hotelBookingRoom.setHasWindow(hotelRoomType.getHasWindow() == 1 ? "有窗" : "無窗");
            if (null == hotelRoomType.getIsFreeNet()) {
                hotelBookingRoom.setIsFreeNet("/");
            } else {
                hotelBookingRoom.setIsFreeNet(hotelRoomType.getIsFreeNet() == 1 ? "免費" : "收費");
            }

            hotelBookingRoomDTOS.add(hotelBookingRoom);
        }

        hotelBookingDetailsDTO.setHotelRooms(hotelBookingRoomDTOS);
        hotelBookingDetailsDTO.setCheckInDate(req.getCheckInDate());
        hotelBookingDetailsDTO.setCheckOutDate(req.getCheckOutDate());
        hotelBookingDetailsDTO.setRoomNum(req.getRoomNum());
        hotelBookingDetailsDTO.setAdultNum(req.getAdultNum());
        hotelBookingDetailsDTO.setChildrenNum(req.getChildrenNum());
        return Result.success(hotelBookingDetailsDTO);
    }

    @Override
    public HotelRoomDTO detailsRoomH5(RoomDetailsQueryH5Req req) {
        req.setAdultNum(req.getAdultNum() == null ? 0 : req.getAdultNum());
        req.setChildrenNum(req.getChildrenNum() == null ? 0 : req.getChildrenNum());
        int totalNum = req.getAdultNum() + req.getChildrenNum();
        req.setPeopleNum(totalNum / req.getRoomNum());

        List<LocalDate> dates = DateUtil.getMiddleDate(req.getCheckInDate(), req.getCheckOutDate());
        int dateType = 2;
        // 如果时间大于1天,则删除最后一天的日期,因为最后一天是离店时间不算入住
        if (dates.size() > 1) {
            dates.remove(dates.size() - 1);
            dateType = 1;
        }
        if (dates.size() == 1) {
            dateType = 2;
        }
        HotelProductDTO hotelBookingProduct = hotelProductMapper.queryProductsH5ByProductid(req, dates, ChannelMainData.APP_H5.getId(), ChannelMainData.CHINA_TRAVEL.getId());
        if (null == hotelBookingProduct) {
            throw new BusinessException(SystemError.HOTEL_10014);
        }

        int days = DateUtil.daysBetween(req.getCheckInDate(), req.getCheckOutDate());
        // 如果天数是0则默认改成1,防止天数为0时价格被变成0
        days = days == 0 ? 1 : days;
        // 提交订单页中酒店价格 = 单价 * 天数 * 房间数
        hotelBookingProduct.setPrice(hotelBookingProduct.getPrice() == null ? BigDecimal.ZERO : hotelBookingProduct.getPrice().multiply(new BigDecimal(days)).multiply(new BigDecimal(req.getRoomNum())).setScale(0, BigDecimal.ROUND_UP));
        // 提交订单页中酒店税费 = 单价 * 天数 * 房间数
        hotelBookingProduct.setTaxation(hotelBookingProduct.getTaxation() == null ? BigDecimal.ZERO : hotelBookingProduct.getTaxation().multiply(new BigDecimal(days)).multiply(new BigDecimal(req.getRoomNum())).setScale(0, BigDecimal.ROUND_UP));
        HotelRoomType hotelRoomType = hotelRoomTypeMapper.selectOne(Wrappers.<HotelRoomType>lambdaQuery()
                .eq(HotelRoomType::getId, hotelBookingProduct.getRoomId())
                .eq(HotelRoomType::getIsDeleted,0));
        if (null == hotelRoomType) {
            throw new BusinessException(SystemError.HOTEL_10014);
        }

        HotelRoomDTO hotelRoomDTO = EntityUtil.copy(hotelRoomType, HotelRoomDTO.class);

        hotelRoomDTO.setHotelProducts(Arrays.asList(hotelBookingProduct));

        hotelRoomDTO.setAreaMeasure(hotelRoomType.getAreaMeasure() + "㎡");
        hotelRoomDTO.setMaxAdult(hotelRoomType.getMaxAdult() + "人");
        hotelRoomDTO.setRoomFloors(hotelRoomType.getRoomFloors() + "層");
        hotelRoomDTO.setAllowSmoke(hotelRoomType.getAllowSmoke() == 1 ? "允許" : "不允許");
        hotelRoomDTO.setCanAddBed(hotelRoomType.getCanAddBed() == 1 ? "可加 " + hotelRoomType.getAddBedNumber() + "張" : "不可加");
        hotelRoomDTO.setHasWindow(hotelRoomType.getHasWindow() == 1 ? "有窗" : "無窗");
        hotelRoomDTO.setHasWindow(hotelRoomType.getHasWindow() == 1 ? "有窗" : "無窗");
        if (null == hotelRoomType.getIsFreeNet()) {
            hotelRoomDTO.setIsFreeNet("/");
        } else {
            hotelRoomDTO.setIsFreeNet(hotelRoomType.getIsFreeNet() == 1 ? "免費" : "收費");
        }

        hotelRoomDTO.setCheckInDate(req.getCheckInDate());
        hotelRoomDTO.setCheckOutDate(req.getCheckOutDate());
        hotelBookingProduct.setRoomNum(req.getRoomNum());
        hotelRoomDTO.setAdultNum(req.getAdultNum());
        hotelRoomDTO.setChildrenNum(req.getChildrenNum());
        return hotelRoomDTO;
    }

}
